
#include <BFont>
#include <BPainter>
#include <BStyle>
#include <BMouseEvent>
#include <BChangeEvent>

#include <BCheckBox>
#include "member_BCheckBox.h"

using namespace BWE;

#define member					(*(member_BCheckBox*)_ptr)
#define member_allocate()		_ptr = new member_BCheckBox(this)
#define member_release()		delete (member_BCheckBox*)_ptr

BCheckBox::BCheckBox(BWidget* parent) : BWidget(parent)
{
	member_allocate();
}
BCheckBox::BCheckBox(const BString& text, BWidget* parent) : BWidget(parent)
{
	member_allocate();
	setText(text);
}
BCheckBox::~BCheckBox()
{
	member_release();
}

void BCheckBox::setAlign(Align align)
{
	if (member.align != align)
	{
		member.align = align;
		this->fresh();
	}
}
Align BCheckBox::align() const
{
	return member.align;
}

void BCheckBox::setText(const BString& text)
{
	if (member.text != text)
	{
		member.text = text;
		this->fresh();
	}
}
const BString& BCheckBox::text() const
{
	return member.text;
}

void BCheckBox::setIconSize(const BSize& iconSize)
{
	if (member.iconSize != iconSize)
	{
		member.iconSize = iconSize;
		this->fresh();
	}
}
const BSize& BCheckBox::iconSize() const
{
	return member.iconSize;
}

void BCheckBox::setIcon(BIcon* icon)
{
	if (member.icon != icon)
	{
		member.icon = icon;
		this->fresh();
	}
}
BIcon* BCheckBox::icon()
{
	return member.icon;
}
const BIcon* BCheckBox::icon() const
{
	return member.icon;
}

void BCheckBox::setChecked(bool checked)
{
	if (member.checked != checked)
	{
		member.checked = checked;
		this->fresh();
		emit(Signal_Checked, member.checked);
	}
}
bool BCheckBox::checked() const
{
	return member.checked;
}

BSize BCheckBox::sizeHint() const
{
	const BRect& crect = this->clientRect();
	BSize hsize = member.iconSize;
	hsize.wrap(crect.size());
	const BFont* font = this->font();
	if(font)
	{
		BSize textSize = font->textSize(member.text);
		hsize.width() += textSize.width();
		hsize.width() = bMax(hsize.width(), textSize.height() * 6);
		hsize.height() = bMax(hsize.height(), textSize.height());
	}
	return hsize + this->shellSize();
}

void BCheckBox::styleEvent(const BEvent& event)
{
	const BStyle* style = this->realStyle();

	const BValue& spaceValue = style->value(Value_Space);
	if (spaceValue.valid())
		member.space = spaceValue;

	const BValue& iconValue = style->value(Value_Icon);
	if (iconValue.valid())
		member.icon = (BIcon*)iconValue;

	const BValue& iconSizeValue = style->value(Value_Icon_Size);
	if (iconSizeValue.valid())
		member.iconSize = iconSizeValue;
}
void BCheckBox::freshEvent(const BEvent& event)
{
	member.freshRects();
}
void BCheckBox::paintEvent(const BEvent& event)
{
	BWidget::paintEvent(event);

	BPainter painter(this);
	if(member.icon)
	{
		State state = State_Normal;
		if (!this->able())
			state = State_Disable;
		if (member.hoverImage)
			state = State_Hovered;
		if (member.checked)
			state = State_Checked;
		painter.drawImage(member.iconRect, member.icon->image(state));
	}
	else
	{
		if(member.hoverImage)
			painter.setColor(Color_Arrow_Hovered);
		else
			painter.setColor(Color_Arrow);
		painter.drawRect(member.iconRect);
		if(member.checked)
		{
			BRect imageRect = member.iconRect * 0.8;
			BPoint p0 = imageRect.leftTop() + BPoint(0, imageRect.height() / 2);
			BPoint p1 = imageRect.leftBottom() + BPoint(imageRect.width() / 2, 0);
			BPoint p2 = imageRect.rightTop();
			painter.setLineSmooth(true);
			painter.setLineWidth(2);
			painter.drawLine(p0, p1);
			painter.drawLine(p1, p2);
		}
	}
	painter.setColor(Color_Text);
	if (member.t_text.size())
		painter.drawText(member.textRect, member.t_text);
	else
		painter.drawText(member.textRect, member.text);
}

void BCheckBox::mouseEnterEvent(const BMouseEvent& mouseEvent)
{
	if (member.state != State_Disable)
	{
		member.state = State_Hovered;
		this->fresh();
	}
	member.hoverImage = false;
}
void BCheckBox::mouseLeaveEvent(const BMouseEvent& mouseEvent)
{
	if (member.state != State_Disable)
	{
		member.state = State_Normal;
		this->fresh();
	}
	member.hoverImage = false;
}

void BCheckBox::mousePressEvent(const BMouseEvent& mouseEvent)
{
	if(member.state != State_Disable )
		member.state = State_Pressed;
	if(member.hoverImage)
	{
		setChecked(!member.checked);
	}
}
void BCheckBox::mouseReleaseEvent(const BMouseEvent& mouseEvent)
{
	if(member.state != State_Disable )
	{
		member.state = State_Hovered;
		this->fresh();
	}
}

void BCheckBox::mouseMoveEvent(const BMouseEvent& mouseEvent)
{
	const BPoint& pos = mouseEvent.pos();
	bool hoverImage = member.iconRect.contain(pos);
	if(member.hoverImage != hoverImage)
	{
		member.hoverImage = hoverImage;
		this->fresh();
	}
}
